package com.xnfh.home.ui.activity

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Rect
import android.os.Bundle
import android.os.SystemClock
import android.text.Editable
import android.text.TextWatcher
import android.view.View
import android.view.animation.Animation
import android.view.animation.RotateAnimation
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter
import com.alibaba.android.arouter.facade.annotation.Route
import com.amap.api.maps.AMap
import com.amap.api.maps.AMap.OnCameraChangeListener
import com.amap.api.maps.AMap.OnMapScreenShotListener
import com.amap.api.maps.AMap.OnMarkerClickListener
import com.amap.api.maps.AMap.OnMarkerDragListener
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CameraPosition
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.MarkerOptions
import com.amap.api.maps.model.Polygon
import com.amap.api.maps.model.PolygonOptions
import com.amap.api.maps.model.Polyline
import com.amap.api.maps.model.PolylineOptions
import com.amap.api.services.core.AMapException
import com.amap.api.services.core.PoiItem
import com.amap.api.services.help.Inputtips
import com.amap.api.services.help.Inputtips.InputtipsListener
import com.amap.api.services.help.InputtipsQuery
import com.amap.api.services.help.Tip
import com.amap.api.services.poisearch.PoiResult
import com.amap.api.services.poisearch.PoiSearch
import com.amap.api.services.poisearch.PoiSearch.OnPoiSearchListener
import com.gyf.immersionbar.ktx.immersionBar
import com.lxj.xpopup.XPopup
import com.lxj.xpopup.core.BasePopupView
import com.lxj.xpopup.interfaces.SimpleCallback
import com.xnfh.common.bean.BaiDuCoddingBean
import com.xnfh.common.bean.CropBean
import com.xnfh.common.constant.ArouterPath
import com.xnfh.framework.base.BaseActivity
import com.xnfh.framework.base.BaseStateObserver
import com.xnfh.framework.log.LogUtil
import com.xnfh.framework.toast.TipsToast
import com.xnfh.home.R
import com.xnfh.home.databinding.ActivityEnclosureFieldBinding
import com.xnfh.home.pop.EnclosureFieldSavePop
import com.xnfh.home.utils.EnclosureMapUtil
import com.xnfh.common.utils.LocationEnclosureUtil
import com.xnfh.framework.utils.PermissionUtils
import com.xnfh.home.viewmodel.EnclosureFieldViewModel
import java.io.File
import java.text.DecimalFormat
import java.util.TreeMap


/**
 * @Description: 快速圈地
 * @Author: ziheng
 * @CreateDate: 2023/11/17 14:34
 * @UpdateUser: ziheng
 * @UpdateDate: 2023/11/17 14:34
 * @UpdateRemark: 更新说明
 */
@Route(path = ArouterPath.HOME.ENCLOSURE_FIELD_ACTIVITY)
class EnclosureFieldActivity : BaseActivity<ActivityEnclosureFieldBinding>(), View.OnClickListener {
    override fun getLayoutID(): Int = R.layout.activity_enclosure_field

    companion object {
        fun start(context: Context) {
            val intent = Intent(context, EnclosureFieldActivity::class.java)
            context.startActivity(intent)
        }
    }

    /*          地图相关        */
    private val latLngList: ArrayList<LatLng> = ArrayList()
    private var isPointComplete = false
    private var aMap: AMap? = null
    private var polygon: Polygon? = null
    private var fieldArea: String? = null
    private var rotateAnimation: RotateAnimation? = null
    private var isNextClick = false
    private val isCircleContinue = true
    private var canAddPolygon = true
    private var polygonOpt: PolygonOptions? = null
    private val markerList: ArrayList<Marker> = ArrayList()
    private val aMapLatLngList: ArrayList<LatLng> = ArrayList()
    private val pointMap: TreeMap<Int, List<LatLng>> = TreeMap()
    private var po11111 = 0
    private var polyline: Polyline? = null
    private var pos = -1 //marker索引
    private var curLatLng: LatLng? = null
    private var currLocation: Marker? = null
    private var isFirstLocation = true
    private var lastBearing = 0f
    private var fieldPolygonOpt: PolygonOptions? = null
    private val tLatLngList: ArrayList<LatLng> = ArrayList()
    private var farmMarker: Marker? = null
    /*          地图相关end        */

    private val viewModel = EnclosureFieldViewModel()
    private var districtId:  String? = null
    private var address: String? = null
    private var imgFile: File? = null
    private var fieldAreaUpdate = 0f
    private var coordinate: String? = null
    //地块信息弹窗
    private var enclosureFieldSavePop:EnclosureFieldSavePop? = null




    override fun init(savedInstanceState: Bundle?) {
        setHeaderTitle(getString(R.string.srt_qd))
        immersionBar {
            statusBarView(R.id.enclosure_title)
        }
        mBind.currentLocationImg.setOnClickListener(this)
        mBind.pointCountryBackoutImg.setOnClickListener(this)
        mBind.pointCountryFlushImg.setOnClickListener(this)
        mBind.enclosureCancel.setOnClickListener(this)
        mBind.enclosureSave.setOnClickListener(this)
        mBind.enclosureMapview.onCreate(savedInstanceState)
        /* 初始化地图相关、回调 */
        initMapView()
        openGps()
        /* 搜索地址的下拉选择框 */
        searchTipsList()
    }


    override fun observe() {
        /**
         * 圈地之后的逆编码
         */
        viewModel.geoCodding.observe(this, object : BaseStateObserver<BaiDuCoddingBean>(null) {
            override fun getRespDataSuccess(it: BaiDuCoddingBean) {
                super.getRespDataSuccess(it)
                districtId = it.addressComponent.adcode
                address = it.formatted_address
                getFieldCropList()
            }
        })
        /**
         * 作物列表
         */
        viewModel.cropList.observe(this,object :BaseStateObserver<List<CropBean>>(null){
            override fun getRespDataSuccess(it: List<CropBean>) {
                super.getRespDataSuccess(it)
                enclosureFieldSavePop?.setPickerData(it)
            }
        })
        /**
         * 圈地添加地块是否成功
         */
        viewModel.addField.observe(this,object :BaseStateObserver<Any>(null){
            override fun getRespDataSuccess(it: Any) {
                super.getRespDataSuccess(it)
                dismissLoadingDialog()
                enclosureFieldSavePop?.dismiss()
                TipsToast.showTips(R.string.str_add_field_success)
                finish()
            }

            override fun getRespDataStart() {
                super.getRespDataStart()
                showLoadingDialog()
            }

            override fun getRespDataError() {
                super.getRespDataError()
                dismissLoadingDialog()
            }
        })
    }

    override fun onClick(v: View?) {
        when (v) {
            mBind.currentLocationImg -> {
                openGps()
            }

            mBind.pointCountryBackoutImg -> {
                isPointComplete = false
                if (latLngList.size > 1) {
                    po11111 -= 1
                    if (pointMap[po11111]!!.size == pointMap[po11111 - 1]!!.size) {
                        val diffIndex: Int =
                            getDiffElementIndex(pointMap[po11111]!!, pointMap[po11111 - 1]!!)
                        if (diffIndex == -1) return
                        markerList[diffIndex].position = pointMap[po11111 - 1]!![diffIndex]
                        latLngList[diffIndex] = markerList[diffIndex].position
                    } else if (pointMap[po11111]!!.size > pointMap[po11111 - 1]!!.size) {
                        markerList[markerList.size - 1].remove()
                        markerList.removeAt(markerList.size - 1)
                        latLngList.removeAt(latLngList.size - 1)
                    }
                    pointMap.remove(po11111)
                    if (polygon != null) {
                        polygon!!.isVisible = false
                        if (latLngList.size > 0) {
                            polygon!!.points = latLngList
                        }
                    }
                    if (latLngList.size > 0) {
                        polyline!!.points = latLngList
                        polyline!!.isVisible = true
                    }
                    LogUtil.d(pointMap[pointMap.size - 1].toString())
                    calculatePerimeterAndArea()
                } else {
                    emptyMap()
                    latLngList.clear()
                    aMapLatLngList.clear()
                }
            }

            mBind.pointCountryFlushImg -> {
                isPointComplete = false
                emptyMap()
                if (polygon != null) polygon!!.isVisible = false
                latLngList.clear()
                aMapLatLngList.clear()
            }

            mBind.enclosureCancel -> {
                showQuitPop()
            }

            mBind.enclosureSave -> {
                if (!mBind.enclosureSave.isEnabled) {
                    TipsToast.showTips(R.string.toast_quandi)
                } else {
                    isNextClick = true
                    viewModel.requestGeoCodding(latLngList[0].latitude.toString() + "," + latLngList[0].longitude)
                    val df = DecimalFormat("0.00")
                    fieldArea = df.format((AMapUtils.calculateArea(latLngList) / 667).toDouble()) + ""
                    shotScreen()
                }
            }
        }
    }

    private fun showQuitPop() {
        XPopup.Builder(this).asConfirm(
            getString(com.xnfh.framework.R.string.str_tips),
            getString(R.string.pop_center_is_quit_qd)
        ) { finish() }.show()
    }
    private fun shotScreen() {
        while (true) {
            if (isInScreen(latLngList)) {
                break
            }
            aMap!!.animateCamera(CameraUpdateFactory.zoomOut())
            SystemClock.sleep(500)
        }
        aMap!!.getMapScreenShot(object : OnMapScreenShotListener {
            override fun onMapScreenShot(bitmap: Bitmap) {
                imgFile = EnclosureMapUtil.getFileByBitmap(this@EnclosureFieldActivity,bitmap)
                //截图结束，展示弹窗
                screenShotEnd()
            }

            override fun onMapScreenShot(bitmap: Bitmap, i: Int) {}
        })
    }


    /**
     * 截图结束
     */
    private fun screenShotEnd() {
        farmMarker!!.position = latLngList[0]
        farmMarker!!.isVisible = true
        polygon!!.points = tLatLngList
        fieldAreaUpdate = fieldArea?.toFloat()!!
        //打开确定弹窗
        enclosureFieldSavePop = EnclosureFieldSavePop(this)
        XPopup.Builder(this)
            .setPopupCallback(object : SimpleCallback() {
                override fun onCreated(popupView: BasePopupView?) {
                    super.onCreated(popupView)
                    enclosureFieldSavePop?.setValue(fieldArea,address)
                    enclosureFieldSavePop?.serOnFieldPopListener(FieldCropList())
                }
            }).asCustom(enclosureFieldSavePop).show()

    }

    /**
     * 保存地块信息弹窗中的回调
     */
    inner class FieldCropList: EnclosureFieldSavePop.OnFieldPopListener{
        override fun selectCropListClick() {
            viewModel.requestCropList()
        }

        override fun saveFiled(
            fieldName: String,
            cropId: String,
            time: Long,
            fieldAreaFinally: Float
        ) {
            if(imgFile == null){
                TipsToast.showTips(R.string.str_jt_null)
                return
            }
            if(coordinate == null){
                TipsToast.showTips(R.string.str_qd_jwd_null)
                return
            }
            viewModel.requestAddField(imgFile!!,fieldName,address!!,fieldAreaFinally,cropId,time,coordinate!!,districtId)
        }
    }


    /**
     * 开启定位
     */
    private fun openGps() {
        PermissionUtils.openGPS(this, object : PermissionUtils.PermissionImp {
            override fun onSuccess(allGranted: Boolean) {
                if (aMap?.isMyLocationEnabled == false) {
                    aMap?.isMyLocationEnabled =
                        true // 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。
                } else if (curLatLng != null) {
                    aMap?.animateCamera(CameraUpdateFactory.newLatLng(curLatLng))
                }
            }

            override fun onField() {
                super.onField()
                if (curLatLng != null) {
                    aMap?.animateCamera(CameraUpdateFactory.newLatLng(curLatLng))
                }
            }
        })
    }


    /**
     * 初始化地图相关
     */
    private fun initMapView() {
        aMap = EnclosureMapUtil.init(
            this,
            mBind.enclosureMapview,
            { latLng ->
                LogUtil.i("------onMapClick-----$latLng====isPointComplete====$isPointComplete")
                try {
                    if (isNextClick) return@init
                    if (!isCircleContinue) return@init
                    if (isPointComplete) return@init
                    if (latLngList.size == 2 && canAddPolygon) {
                        polygon = aMap!!.addPolygon(polygonOpt)
                        canAddPolygon = false
                    }
                    val myMarker: Marker = if (markerList.isEmpty()) {
                        aMap!!.addMarker(
                            MarkerOptions().position(latLng)
                                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.vertex_marker_max_img))
                                .anchor(0.5f, 0.5f).draggable(true)
                        )
                    } else {
                        aMap!!.addMarker(
                            MarkerOptions().position(latLng)
                                .icon(BitmapDescriptorFactory.fromResource(R.mipmap.vertex_marker_min_img))
                                .anchor(0.5f, 0.5f).draggable(true)
                        )
                    }
                    myMarker.setObject(latLngList.size)
                    markerList.add(myMarker)
                    latLngList.add(latLng)
                    EnclosureMapUtil.wgs84ToGcj02(this, latLng)?.let { aMapLatLngList.add(it) }
                    val pointList: MutableList<LatLng> = java.util.ArrayList()
                    pointList.addAll(latLngList)
                    pointMap[po11111] = pointList
                    LogUtil.d(pointMap[pointMap.size - 1].toString())
                    po11111++
                    polyline?.points = latLngList
                    if (latLngList.size > 0) {
                        mBind.pointCountrySearchAddressAutoTxt.visibility = View.VISIBLE
                        mBind.enciosureBottomMuea.visibility = View.VISIBLE
                        mBind.enclosureEndMuea.visibility = View.VISIBLE
                    } else {
                        mBind.enciosureBottomMuea.visibility = View.GONE
                        mBind.enclosureEndMuea.visibility = View.GONE
                    }
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            },
            object : OnMarkerDragListener {
                override fun onMarkerDragStart(marker: Marker?) {
                    pos = marker?.getObject() as Int
                }

                override fun onMarkerDrag(marker: Marker?) {
                    if (pos != -1) {
                        latLngList[pos] = marker?.position!!
                        polyline!!.points = latLngList
                        if (latLngList.size >= 3 && isPointComplete) {
                            polygon!!.points = latLngList
                        }
                    }
                }

                override fun onMarkerDragEnd(marker: Marker?) {
                    calculatePerimeterAndArea()
                    markerList[pos].position = marker?.position
                    val pointList: MutableList<LatLng> = java.util.ArrayList()
                    pointList.addAll(latLngList)
                    pointMap[po11111] = pointList
                    LogUtil.d(pointMap[pointMap.size - 1].toString())
                    po11111++
                }
            },
            {
                aMap!!.animateCamera(CameraUpdateFactory.newLatLngZoom(curLatLng, 18f))
            },
            { location ->
                if (location != null) {
                    val latitude: Double = location.latitude
                    val longitude: Double = location.longitude
                    curLatLng = LatLng(
                        LocationEnclosureUtil.GCJ2WGSLat(latitude, longitude),
                        LocationEnclosureUtil.GCJ2WGSLon(latitude, longitude)
                    )
                    if (currLocation == null) {
                        currLocation = aMap!!.addMarker(
                            MarkerOptions().position(curLatLng)
                                .icon(BitmapDescriptorFactory.fromResource(com.xnfh.common.R.mipmap.arrows_img))
                                .anchor(0.5f, 0.5f)
                        )
                    } else {
                        currLocation?.position = curLatLng
                    }
                    if (isFirstLocation) {
                        aMap!!.animateCamera(CameraUpdateFactory.newLatLng(curLatLng))
                        isFirstLocation = false
                    }
                }
            },
            object : OnCameraChangeListener {
                override fun onCameraChange(cameraPosition: CameraPosition?) {
                    cameraPosition?.bearing?.let { startIvCompass(it) }
                }

                override fun onCameraChangeFinish(p0: CameraPosition?) {
                }
            },
            object : OnMarkerClickListener {
                override fun onMarkerClick(marker: Marker?): Boolean {
                    if (marker?.getObject() as Int == 0 && latLngList.size >= 3) {
                        isPointComplete = true
                        polygon?.points = ArrayList<LatLng>()
                        polygon?.fillColor = -0x7f9e0201
                        polygon?.strokeColor = -0xbf6302
                        polygon?.points = latLngList
                        polygon?.isVisible = true
                        calculatePerimeterAndArea()
                    }
                    return true
                }
            }
        )
        polyline = aMap?.addPolyline(PolylineOptions().color(-0xbf6302).width(8f))
        polyline!!.zIndex = 2f
        polygonOpt = PolygonOptions().fillColor(-0x7f0b1286).strokeColor(-0x28ca).strokeWidth(8f)
        polygonOpt?.zIndex(3f)
        fieldPolygonOpt =
            PolygonOptions().fillColor(0x4D3E9BFD).strokeColor(-0xbf6302).strokeWidth(8f)
        fieldPolygonOpt?.zIndex(2f)

        farmMarker =
            aMap!!.addMarker(MarkerOptions().icon(BitmapDescriptorFactory.fromResource(R.mipmap.point_country_farm_location_img)))
        farmMarker?.isClickable = false
    }

    private fun startIvCompass(bearing: Float) {
        var bearing = bearing
        bearing = 360 - bearing
        rotateAnimation = RotateAnimation(
            lastBearing,
            bearing,
            Animation.RELATIVE_TO_SELF,
            0.5f,
            Animation.RELATIVE_TO_SELF,
            0.5f
        )
        rotateAnimation?.fillAfter = true
        mBind.encloseureCompass.startAnimation(rotateAnimation)
        lastBearing = bearing
    }

    /**
     * 实时计算面积
     */
    private fun calculatePerimeterAndArea() {
        if (latLngList.size == 1 || latLngList.size == 2 || !isPointComplete) {
            mBind.enclosureSave.isEnabled = false
            return
        }
        val df = DecimalFormat("0.00")
        fieldArea = df.format((AMapUtils.calculateArea(latLngList) / 667).toDouble()) + ""
        mBind.enclosureSave.isEnabled = true
    }

    private fun getDiffElementIndex(lateList: List<LatLng>, previousList: List<LatLng>): Int {
        for (i in previousList.indices) {
            if (!lateList.contains(previousList[i])) return i
        }
        return -1
    }

    private fun emptyMap() {
        for (i in markerList.indices) {
            markerList[i].remove()
        }
        markerList.clear()
        tLatLngList.clear()
        tLatLngList.addAll(latLngList)
        po11111 = 0
        pos = -1
        pointMap.clear()
        if (polygon != null) polygon!!.points = java.util.ArrayList()
        polyline!!.points = java.util.ArrayList()
        polyline!!.isVisible = true
        mBind.enciosureBottomMuea.visibility = View.VISIBLE
        mBind.enclosureSave.isEnabled = false
    }

    /**
     * 搜索框输入，下拉提示框
     */
    private fun searchTipsList() {
        mBind.pointCountrySearchAddressAutoTxt.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {

            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                val newText = s.toString().trim { it <= ' ' }
                if (newText.isNotEmpty()) {
                    val inputquery = InputtipsQuery(newText, "")
                    val inputTips = Inputtips(this@EnclosureFieldActivity, inputquery)
                    inputTips.setInputtipsListener(object : InputtipsListener {
                        override fun onGetInputtips(tipList: MutableList<Tip>?, rCode: Int) {
                            if (rCode == AMapException.CODE_AMAP_SUCCESS) {
                                // 正确返回
                                val listString: MutableList<String> = java.util.ArrayList()
                                for (i in tipList!!.indices) {
                                    listString.add(tipList[i].name)
                                }
                                val aAdapter = ArrayAdapter(
                                    applicationContext,
                                    R.layout.item_enclosure_tips, listString
                                )
                                mBind.pointCountrySearchAddressAutoTxt.setAdapter(aAdapter)
                                aAdapter.notifyDataSetChanged()
                            }
                        }

                    })
                    inputTips.requestInputtipsAsyn()
                }
            }

            override fun afterTextChanged(s: Editable?) {
            }

        })

        mBind.pointCountrySearchAddressAutoTxt.setOnEditorActionListener { textView, actionId, keyEvent ->
            if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                if (mBind.pointCountrySearchAddressAutoTxt.text.isNullOrBlank()) {
                    TipsToast.showTips(R.string.toast_search_null_tips)
                } else {
                    showLoadingDialog()
                    val query = PoiSearch.Query(
                        mBind.pointCountrySearchAddressAutoTxt.text.toString(),
                        "",
                        ""
                    )
                    query.pageSize = 10
                    query.pageNum = 0
                    val poiSearch = PoiSearch(this, query)
                    poiSearch.setOnPoiSearchListener(object : OnPoiSearchListener {
                        override fun onPoiSearched(result: PoiResult?, rCode: Int) {
                            dismissLoadingDialog() // 隐藏对话框

                            if (rCode == AMapException.CODE_AMAP_SUCCESS && result != null &&
                                result.query != null && result.query == query && !result.pois.isNullOrEmpty()
                            ) {
                                // 取得搜索到的poiitems有多少页
                                val poiItems: List<PoiItem> = result.pois
                                // 取得第一页的poiitem数据，页数从数字0开始
                                val latitude = poiItems[0].latLonPoint.latitude
                                val longitude = poiItems[0].latLonPoint.longitude
                                val to84Lat: Double =
                                    LocationEnclosureUtil.GCJ2WGSLat(
                                        latitude,
                                        longitude
                                    )
                                val to84Lon: Double =
                                    LocationEnclosureUtil.GCJ2WGSLon(
                                        latitude,
                                        longitude
                                    )
                                EnclosureMapUtil.addMarker(LatLng(to84Lat, to84Lon))
                                aMap!!.animateCamera(
                                    CameraUpdateFactory.newLatLngZoom(
                                        LatLng(
                                            to84Lat,
                                            to84Lon
                                        ), 12f
                                    )
                                )
                            } else {
                                TipsToast.showTips(R.string.toast_search_null_address_tips)
                            }
                        }

                        override fun onPoiItemSearched(p0: PoiItem?, p1: Int) {
                        }

                    })
                    poiSearch.searchPOIAsyn()
                }
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(textView.windowToken, 0) //强制隐藏键盘
            }
            return@setOnEditorActionListener false
        }
    }

    private fun isInScreen(list: List<LatLng>): Boolean {
        val projection = aMap!!.projection
        val manager = this.windowManager
        val windth = manager.defaultDisplay.width
        val height = manager.defaultDisplay.height
        val scale = resources.displayMetrics.density
        val d = 50 * scale + 0.5 //标题高度px
        val outRect = Rect()
        window.decorView.getWindowVisibleDisplayFrame(outRect)
        val minHeight = outRect.top + d.toInt()
        for (i in list.indices) {
            val latLng = list[i]
            val clickPoint = projection.toScreenLocation(latLng)
            return if (clickPoint.x > 0 && clickPoint.x < windth && clickPoint.y > 0 && clickPoint.y < height - minHeight) {
                continue
            } else {
                false
            }
        }
        return true
    }

    /**
     * 获取每个点的经纬度
     */
    private fun getFieldCropList() {
        var i = 0
        val ln = latLngList.size
        val coordinates = Array(ln) {
            DoubleArray(
                2
            )
        }
        while (i < ln) {
            val latLng = latLngList[i]
            coordinates[i][0] = latLng.longitude
            coordinates[i][1] = latLng.latitude
            i++
        }
        coordinate = com.xnfh.framework.utils.JsonUtlis.Convert2DDoubleArrayToJson(coordinates)
    }

    override fun goBack(view: View) {
        showQuitPop()
    }


    override fun onDestroy() {
        mBind.enclosureMapview.onDestroy()
        EnclosureMapUtil.destory()
        super.onDestroy()
    }

}